using System;
using System.Collections.Generic;
using System.Text;
using PDSClient.Simple.Impl;

namespace PDSClient.Communication
{
    /// <summary>
    /// An abstract mechanism for actively initiating a IClientConnection.
    /// </summary>
    /// <see cref="IClientConnection"/>
    public abstract class ClientConnector
    {
        /* The static singleton factory */
        private static IClientConnectorFactory factory = new SimpleClientConnectorFactory();

        /// <summary>
        /// Sets the {@link ClientConnectorFactory} that will be used to create new ClientConnectors.
        /// </summary>
        /// <param name="factory">the IClientConnectorFactory to create new ClientConnectors</param>
        public static void SetClientConnectorFactory(IClientConnectorFactory factory)
        {
            ClientConnector.factory = factory;
        }
        /// <summary>
        /// Creates a ClientConnector according to the given properties
        /// </summary>
        /// <param name="properties">properties which affect the implementation of the ClientConnector returned</param>
        /// <returns>a ClientConnector</returns>
        public static ClientConnector Create(IDictionary<string, string> properties) 
        {
            return factory.CreateConnector(properties);
        }

        protected ClientConnector() { }

        /// <summary>
        /// Actively initates a connection to the target remote address.
        /// This call is non-blocking. IClientConnectionListener.Connected()
        /// will be called asynchronously on the listener upon successful
        /// connection, or IClientConnectionListener.Disconnected() if it
        /// fails.
        /// </summary>
        /// <exception cref="IOException">if an IO error occurs synchronously</exception>
        /// <exception cref="SecurityException">SecurityException if a security manager has been installed
        /// and it does not permit access to the remote endpoint</exception>
        /// <param name="listener">the listener for all IO events on the</param>
        public abstract void Connect(IClientConnectionListener listener);

        /// <summary>
        /// Cancels a pending connect operation on this IClientConnecton.
        /// </summary>
        /// <exception cref="IOException">if an IO error occurs synchronously</exception>
        public abstract void Cancel();
    }
}
